<?php

class PageRevisionService extends FServiceBase
{    
    /**
    * Get a PageRevision model given its ID
    * 
    * @param int id PageRevision ID
    * @return FServiceModel
    */
    public function get($params){
        $id = $this->getParam($params, 'id',1);
        $pageId = $this->getParam($params, 'page_id',0);
        $model = PageRevision::model()->findByAttributes(array(
            'id'=>$id,
            'page_id'=>$pageId,
        ));
        if (! $model)
            $this->result->fail(ERROR_INVALID_DATA, Yii::t('CmsModule.PageRevision','Invalid ID.'));
        $this->result->processed('model', $model);
        return $this->result;
    }
    
    public function save($params) {
        /**
        * @var CModel
        */
        $model = $this->getModel($params['PageRevision'],'PageRevision');
        $type = $this->getParam($params, 'type', null);
        $this->result->processed('model', $model);
        
        $attributes = $model->attributes;
        /*if ($type == Page::TYPE_STANDARD)
        {
            unset($attributes['template_content_id']);
        }*/
        $attributes = array_keys($attributes);
        if (! $model->validate($attributes))
            $this->result->fail(ERROR_INVALID_DATA, Yii::t('CmsModule.PageRevision', 'Submitted data is missing or invalid.'));
        elseif ($this->getParam($params, 'validateOnly',0) == TRUE)
            return $this->result;
        elseif (! $model->save(false, $attributes))
            $this->result->fail(ERROR_HANDLING_DB, Yii::t('CmsModule.PageRevision','Error while saving submitted data into database.'));
        
        return $this->result;
    }


    public function delete($params) {
        //Yii::trace(__CLASS__.'::'.__FUNCTION__, __CLASS__);
        $id = $this->getParam($params, 'revision', 0);
        $pageId = $this->getParam($params, 'page_id', 0);
        $deleteTemplate = $this->getParam($params, 'delete_template', false);
        $deleteWidgetData = $this->getParam($params, 'delete_widget_data', false);
        
        if (($id && $pageId) == false) {
            return $this->result->fail(ERROR_INVALID_DATA, Yii::t('CmsModule.PageRevision','Invalid ID.'.CVarDumper::dumpAsString($id).';'.CVarDumper::dumpAsString($pageId)));
        }
        
        //is active in any workflow
        $criteria = new CDbCriteria();
        $criteria->compare('page_id', $pageId);
        $criteria->compare('revision', $id);
        if (PageCurrentRevision::model()->exists($criteria))
        {
            return $this->result->fail(ERROR_INVALID_DATA, Yii::t('CmsModule.PageRevision', "Can't delete revision is active in workflow."));
        }
      
        $pageRevision = PageRevision::model()->findByAttributes(array('id'=>$id, 'page_id'=>$pageId));
        if (is_object($pageRevision))
        {
            $pageWidgets = PageWidget::model()->findAllByAttributes(array('revision_id'=>$id, 'page_id'=>$pageId));
            if (count($pageWidgets))
            {
                foreach ($pageWidgets as $pageWidget)
                {
                    //delete widget_data
                    if ($deleteWidgetData)
                    {
                        $isUsed = FSM::_run('Cms.widgetData.isUsed', array('id'=>$pageWidget->widget_data_id,'exclude'=>array($pageWidget->page_id)))->status;
                        if (! $isUsed)
                        {
                            FSM::_run('Cms.widgetData.delete', array('ids'=>array($pageWidget->widget_data_id)));
                        }
                    }
                    //check can delete template, template content
                    if ($deleteTemplate)
                    {
                        $result = FSM::_run('Cms.templateContent.isUsed', array('id'=>$pageRevision->template_content_id,'exclude'=>array($pageWidget->page_id)));
                        //delete template content
                        if (! $result->status)
                        {
                            FSM::_run('Cms.templateContent.delete', array('ids'=>array($pageRevision->template_content_id)));
                        }
                        if ($result->canDeleteTemplate)
                        {
                            FSM::_run('Cms.template.delete', array('ids'=>array($result->canDeleteTemplate)));
                        }
                    }
                    //delete page_widget
                    $pageWidget->delete();
                }
            }
            if (!$pageRevision->delete())
            {
                Yii::log(CVarDumper::dumpAsString($pageRevision->getErrors()), Clogger::LEVEL_ERROR, __CLASS__);
            }
        }
        else
        {
            $this->result->fail(ERROR_INVALID_DATA, Yii::t('CmsModule.PageRevision','Not found page revision.'));
        }

        return $this->result;
    }
    
    public function getAvailableRevisions($params)
    {
        $pageId = $this->getParam($params, 'page_id', 0);
        
        $criteria = new CDbCriteria();
        $criteria->compare('page_id', $pageId);
        $criteria->order = 'id DESC';
        $models = PageRevision::model()->findAll($criteria);
        if (count($models))
            $models = CHtml::listData($models, 'id', 'id');
        $this->result->processed('revisions', $models);
        return $this->result;
    }
    
    public function getNextRevision($params)
    {
        $revisions = $this->getAvailableRevisions($params)->revisions;
        if (is_array($revisions) && count($revisions))
            $revision = array_shift($revisions);
        else
            $revision = 0;
        $revision++;
        $this->result->processed('revision', $revision);
        return $this->result;
    }
    
    public function updateBy($params)
    {
        $id = $this->getParam($params, 'id', 0);
        $pageId = $this->getParam($params, 'page_id', 0);
        
        $criteria = new CDbCriteria();
        $criteria->compare('id', $id);
        $criteria->compare('page_id', $pageId);
        $status = PageRevision::model()->updateAll(array(
            'updated_by'=>Yii::app()->user->id,
            'last_update'=>date('Y-m-d H:i:s'),
        ), $criteria);
        $this->result->processed('status', $status);
        return $this->result;
    }
    
    public function getCurrent($params)
    {
        $pageId = $this->getParam($params, 'page_id', 0);
        $workflowUrl = $this->getParam($params, 'workflow_url', null);

        $result = FSM::_run('Cms.Workflow.lookup', array('host'=>$workflowUrl));
        if (!$result->hasErrors())
        {
            $workflow = $result->model;
            $db = Yii::app()->db;
            $command = $db->createCommand('SELECT revision FROM '.SITE_TABLE_PREFIX.'page_current_revision WHERE page_id=:page_id AND workflow_id=:workflow_id');
            $command->bindValue(':page_id', $pageId, PDO::PARAM_INT);
            $command->bindValue(':workflow_id', $workflow->id, PDO::PARAM_INT);
            $revision = $command->queryScalar();
        }
        else
            $revision = 1;
        
        $this->result->processed('revision', $revision);
        return $this->result;
    }
    
    public function getCurrentByPage($params)
    {
        $pageId = $this->getParam($params, 'page_id', 0);
        
        $db = Yii::app()->db;
        $command = $db->createCommand('SELECT revision, workflow_id FROM '.SITE_TABLE_PREFIX.'page_current_revision WHERE page_id=:page_id');
        $command->bindValue(':page_id', $pageId, PDO::PARAM_INT);
        $command->bindValue(':workflow_id', $workflow->id, PDO::PARAM_INT);
        $revisions = $command->queryRow();
        
        $this->result->processed('revisions', $revisions);
        return $this->result;
    }
    
    public function deleteAll($params)
    {
        $pageId = $this->getParam($params, 'page_id', 0);
        PageRevision::model()->deleteAllByAttributes(array('page_id'=>$pageId));
        $this->result;
    }
    
    public function activeWorkflow($params)
    {
        $pageId = $this->getParam($params, 'page_id', 0);
        $revision = $this->getParam($params, 'revision', 0);
        $workflowIds = $this->getParam($params, 'workflow_id', array());
        $oldWorkflowIds = $this->getParam($params, 'old_workflow_id', array());
        
        $status = false;
        if (is_array($workflowIds) && count($workflowIds) && $pageId && $revision)
        {
            $workflowIds = array_map('CPropertyValue::ensureInteger', $workflowIds);
            $db = Yii::app()->db;
            //remove old current
            $command = $db->createCommand();
            $command->delete(SITE_TABLE_PREFIX.'page_current_revision', array(
                'and', 
                'page_id='.$pageId,
                array('in', 'workflow_id', $workflowIds),
            ));
            
            foreach ($workflowIds as $workflowId)
            {
                //insert
                $command->insert(SITE_TABLE_PREFIX.'page_current_revision', array(
                    'page_id'=>$pageId,
                    'workflow_id'=>$workflowId,
                    'revision'=>$revision,
                ));
            }
            //remove active workflow
            if (count($oldWorkflowIds))
            {
                $diff = array_diff($oldWorkflowIds, $workflowIds);
                $diff = array_filter($diff, 'strlen');
                if (count($diff))
                {
                    $command->delete(SITE_TABLE_PREFIX.'page_current_revision', array(
                        'and', 
                        'page_id='.$pageId,
                        array('in', 'workflow_id', $diff),
                    ));
                }
            }
            $status = true;
        }
        //update page url cache
        if ($status)
        {
            $page = Page::model()->findByPk($pageId);
            if (is_object($page))
                FSM::_run('Cms.pageUrl.updateCacheUrlBySite',array('site_id' => $page->site_id));
        }
        $this->result->processed('status', $status);
        return $this->result;
    }
    
    public function updateTemplate($params) {
        $model = $this->getModel($params['PageRevision'],'PageRevision');
        $containers = $this->getParam($params, 'containers', array(), 'xss, newline, tag');
        
        $pageRevision = PageRevision::model()->findByAttributes(array(
            'id'=>$model->id,
            'page_id'=>$model->page_id,
        ));
        if (!is_object($pageRevision))
        {
            $this->result->processed('model', $model);
            $this->result->fail(ERROR_INVALID_DATA, Yii::t('CmsModule.PageRevision', 'Submitted data is missing or invalid.'));
            return $this->result;
        }
        
        $tplContentIdOld = $pageRevision->template_content_id;
        $pageRevision->attributes = $model->attributes;
        $this->result->processed('model', $pageRevision);
        
        if (! $pageRevision->validate())
            $this->result->fail(ERROR_INVALID_DATA, Yii::t('CmsModule.PageRevision', 'Submitted data is missing or invalid.'));
        elseif ($this->getParam($params, 'validateOnly',0) == TRUE)
            return $this->result;
        else
        {
            if (!$pageRevision->save(false, array('template_content_id', 'js_files', 'css_files', 'log', 'seo_title')))
                $this->result->fail(ERROR_HANDLING_DB, Yii::t('CmsModule.PageRevision','Error while saving submitted data into database.'));
                
            if ($pageRevision->template_content_id != $tplContentIdOld)
            {
                //remove link widgets of tempalte from page
                $containers = FSM::_run('Cms.templateContent.unlinkWidgetsFromPage', array(
                    'page_id'=>$model->page_id,
                    'revision_id'=>$model->id,
                    'template_content_id'=>$tplContentIdOld,
                    'containers'=>$containers,
                ))->containers;
                //link widgets of new template to page
                $containers = FSM::_run('Cms.templateContent.linkWidgetsToPage', array(
                    'page_id'=>$model->page_id,
                    'revision_id'=>$model->id,
                    'template_content_id'=>$pageRevision->template_content_id,
                    'containers'=>$containers,
                ))->containers;
            }
        }
        
        return $this->result->processed('containers', $containers);
    }
    
    public function copyFromTemplate($params)
    {
        $type = $this->getParam($params, 'type', '');
        $pageId = $this->getParam($params, 'page_id', 0);
        $revisionId = $this->getParam($params, 'revision_id', 0);
        $templateContentId = $this->getParam($params, 'template_content_id', 0);
        if (!$pageId || !$revisionId || !$templateContentId || empty($type))
        {
            $this->result->fail(ERROR_INVALID_DATA, Yii::t('CmsModule.PageRevision', 'Submitted data is missing or invalid.'));
        }
        else
        {
            $templateContent = TemplateContent::model()->findByPk($templateContentId);
            $criteria = new CDbCriteria();
            $criteria->compare('page_id', $pageId);
            $criteria->compare('id', $revisionId);
            $attributes = array();
            if ($type == 'js')
            {
                $jsFiles = $templateContent->js_files;
                $jsFiles = var_export($jsFiles, true);
                $attributes = array('js_files'=>$jsFiles);
            }
            elseif ($type == 'css')
            {
                $cssFiles = $templateContent->css_files;
                $cssFiles = var_export($cssFiles, true);
                $attributes = array('css_files'=>$cssFiles);
            }
            PageRevision::model()->updateAll($attributes, $criteria);
        }
        return $this->result;
    }
    
    /**
    * copy page revision from site to site
    * 
    * @param array $params
    * <ul>
    *   <li>source_site_id: int, required, copy page to source site_id</li>
    *   <li>target_site_id: int, required, copy page to target site_id</li>
    *   <li>source_page_id: int, required, copy from source page_id</li>
    *   <li>target_page_id: int, required, copy to target page_id</li>
    *   <li>active_workflow: boolean, Automatical set active revisions if target workflow found</li>
    *   <li>revisions: array,  array('all', 'active') Which revisions you want to copy</li>
    * </ul>
    * 
    * @return FServiceModel
    */
    public function copy($params)
    {
        $sourceSiteId = $this->getParam($params, 'source_site_id', 0);
        $targetSiteId = $this->getParam($params, 'target_site_id', 0);
        $sourcePageId = $this->getParam($params, 'source_page_id', 0);
        $targetPageId = $this->getParam($params, 'target_page_id', 0);
        $activeWorkflow = $this->getParam($params, 'active_workflow', false);
        $linkData = $this->getParam($params, 'link_data', false);
        $copyRevision = isset($params['copy_revision']) ? $params['copy_revision'] : 'all';//$copyRevision = $this->getParam($params, 'copy_revision', 'all');
        //normalize copy revision
        if (!in_array($copyRevision, array('all','active')))
            $copyRevision = (int) $copyRevision;
        
        $models = array();
        if ($sourcePageId && $targetPageId)
        {
            // find revision(s) to copy
            $criteria = new CDbCriteria();
            $criteria->compare('"t".page_id', $sourcePageId);
            if ($copyRevision == 'active')
            {
                $criteria->distinct = true;
                $criteria->join = 'INNER JOIN '.SITE_TABLE_PREFIX.'page_current_revision pcr ON "pcr".page_id = "t".page_id AND "pcr".revision = "t".id';
            }
            elseif (is_int($copyRevision))
            {
                $criteria->compare('"t".id', $copyRevision);
            }
            $criteria->order = '"t".id ASC';
            $items = PageRevision::model()->findAll($criteria);
            
            // begin copy revision(s)
            if (count($items))
            {
                $revisionsTranfer = array();
                foreach ($items as $model)
                {
                    $sourceRevisionId = $model->id;
                    $targetRevisionId = (int) FSM::_run('Cms.PageRevision.getNextRevision',array('page_id'=>$targetPageId))->revision;
                    /**
                    * @var PageRevision
                    */
                    $model->setIsNewRecord(true);
                    $model->page_id = $targetPageId;
                    $model->id = $targetRevisionId;
                    $model->log = "Copy from page#{$sourcePageId}, rev#{$sourceRevisionId}";
                    if ($model->save())
                    {
                        array_push($models, $model);
                        $revisionsTranfer[$sourceRevisionId] = $targetRevisionId;
                    }
                    else
                    {
                        Yii::log(CVarDumper::dumpAsString($model->getErrors()), CLogger::LEVEL_ERROR);
                    }
                }
                if (count($revisionsTranfer))
                {
                    //[---active target workflow
                    if ($activeWorkflow)
                    {
                        //[[--find revision have active workflow 
                        $db = Yii::app()->db;
                        $command = $db->createCommand();
                        $actives = $command->select('w.name, pcr.revision')
                            ->from(SITE_TABLE_PREFIX.'workflow w')
                            ->join(SITE_TABLE_PREFIX.'page_current_revision pcr', '"pcr".workflow_id = "w".id')
                            ->where('"pcr".page_id = :page_id AND "w".site_id = :site_id', array(':page_id'=>$sourcePageId, ':site_id'=>$sourceSiteId))
                            ->queryAll();
                        //---find revision have active workflow]]
                        if (count($actives))
                        {
                            foreach ($actives as $data)
                            {
                                $criteria = new CDbCriteria();
                                $criteria->compare('name', $data['name'], true);
                                $criteria->compare('site_id', $targetSiteId);
                                $model = Workflow::model()->find($criteria);
                                // if target site has this workflow, activate target page
                                if (is_object($model) && isset($revisionsTranfer[$data['revision']]))
                                {
                                    FSM::_run('Cms.PageRevision.activeWorkflow', array(
                                        'page_id'=>$targetPageId,
                                        'revision'=>$revisionsTranfer[$data['revision']],
                                        'workflow_id'=>array($model->id),
                                    ));
                                }
                            }
                        }
                    }
                    //---active target workflow]
                    //copy page_widget
                    FSM::_run('Cms.PageWidget.copy', array(
                        'source_page_id'=>$sourcePageId,
                        'target_page_id'=>$targetPageId,
                        'revisions_transfer'=>$revisionsTranfer,
                        'link_data'=>$linkData,
                    ));
                }
                
                //update relationship template_site
                $templateContentIds = CHtml::listData($items, 'template_content_id', 'template_content_id');
                $criteria = new CDbCriteria();
                $criteria->select = 'template_id';
                $criteria->distinct = true;
                $criteria->addInCondition('id', $templateContentIds);
                $models = TemplateContent::model()->findAll($criteria);
                if (count($models))
                    $templateIds = CHtml::listData($models, 'template_id', 'template_id');
                else
                    $templateIds = array();
                FSM::_run('Cms.template.updateTemplateSite', array('site_id'=>$targetSiteId, 'template_id'=>$templateIds));
            }
        }
        else
            $this->result->fail(ERROR_INVALID_DATA, Yii::t('CmsModule.Page', 'Submitted data is missing or invalid.'));
            
        $this->result->processed('models', $models);
        
        return $this->result;
    }
    
    public function isTemplateUsed($params)
    {
        $templateId = $this->getParam($params, 'template_id', 0);
        
        $criteria = new CDbCriteria();
        $criteria->join = 'INNER JOIN '.SITE_TABLE_PREFIX.'template_content tc ON tc.id = t.template_content_id';
        $criteria->compare('tc.template_id', $templateId);
        $result = PageRevision::model()->exists($criteria);
        return $this->result->processed('exists', $result);
    }
}
